﻿using Newtonsoft.Json;
using System.Diagnostics;

namespace Wargame_V3_1
{
    public class OperatorModel
    {
        private string _name;  // 模型名称，与算子子类型（subType）一致
        private Dictionary<string, string> _model;  // 算子模型，记录该类型算子的所有属性及属性类型
        private Dictionary<string, Dictionary<string, string>> _codeTexts;  // 代码文本，从代码文件中读取到的；CodeText["CalloutAction"]["Type"]="cs", CodeText["CalloutAction"]["Code"]="..."
        private string[] _allowedFile = new string[] { "cs" };  // 支持输入的文件类型

        public string Name { get => _name; }
        public Dictionary<string, string> Model { get => _model; }
        public Dictionary<string, Dictionary<string, string>> CodeTexts { get => _codeTexts; }

        public OperatorModel(string modelName, string modelPath)
        {
            _name = modelName;
            if (File.Exists(modelPath + @"\Model.json"))
            {
                Dictionary<string, string> oprMethods = new Dictionary<string, string>();
                using (StreamReader sr = new StreamReader(modelPath + @"\Model.json"))
                {
                    string data = sr.ReadToEnd();
                    Dictionary<string, object> allInfo = JsonConvert.DeserializeObject<Dictionary<string, object>>(data);
                    _model = JsonConvert.DeserializeObject<Dictionary<string, string>>(allInfo["Attributes"].ToString());
                    oprMethods = JsonConvert.DeserializeObject<Dictionary<string, string>>(allInfo["Methods"].ToString());
                }
                _codeTexts = new Dictionary<string, Dictionary<string, string>>();
                foreach (KeyValuePair<string, string> methodItem in oprMethods)
                {
                    string methodName = methodItem.Key;
                    string methodFile = methodItem.Value;
                    if (File.Exists(modelPath + "\\" + methodFile))
                    {
                        string codeType = methodFile.Split('.').Last();
                        if (_allowedFile.Contains(codeType))
                        {
                            string code = File.ReadAllText(modelPath + "\\" + methodFile);
                            _codeTexts.Add(methodName, new Dictionary<string, string>() { { "Type", codeType }, { "Code", code } });
                        }
                        else
                        {
                            Trace.TraceWarning($"暂时不支持此类型的代码：{methodFile}。");
                            continue;
                        }
                    }
                    else
                    {
                        Trace.TraceError($"输入的文件路径中缺少代码文件{methodFile}。");
                        throw new Exception($"输入的文件路径中缺少代码文件{methodFile}。");
                    }
                }
            }
            else
            {
                Trace.TraceError("输入的文件路径中缺少Model.json文件。");
                throw new Exception("输入的文件路径中缺少Model.json文件。");
            }
        }

        /// <summary>
        /// 判断当前类对象是否合法
        /// </summary>
        /// <returns></returns>
        public bool IsValid()
        {
            if (_name == null || _name == "") return false;
            if (_model == null || _model.Count == 0) return false;
            return true;
        }

        public Operator CreateOprInstance(Dictionary<string, object> oprInfo)
        {
            Operator opr = new Operator(_model, oprInfo);
            foreach (KeyValuePair<string, Dictionary<string, string>> item in _codeTexts)
            {
                opr.SetMethod(item.Key, item.Value["Code"], item.Value["Type"]);
            }
            return opr;
        }
    }

    // old版本
    //public class OperatorModel
    //{
    //    private string _name;  // 模型名称，与算子子类型（subType）一致
    //    private string _type;  // 模型类型，文件后缀名，主要包括C#代码文件（CS）等
    //    private string _codeText;  // 代码文本，从代码文件中读取到的
    //    private string[] _allowedFile = new string[] { "cs" };  // 支持输入的文件类型

    //    public string Name { get => _name; }
    //    public string Type { get => _type; }
    //    public string CodeText { get => _codeText; }

    //    public OperatorModel(string filePath)
    //    {
    //        string fileName = filePath.Split('\\').Last();// TankOpr.cs
    //        if (fileName.Contains('.'))
    //        {
    //            string[] fileNameSplit = fileName.Split('.');// TankOpr cs
    //            if (_allowedFile.Contains(fileNameSplit.Last()))// 包含文件后缀，例如cs
    //            {
    //                _name = fileNameSplit[0].Replace("Opr", "");
    //                _type = fileNameSplit.Last();
    //            }
    //            else
    //            {
    //                return;
    //            }
    //        }
    //        else
    //        {
    //            Trace.TraceError("输入的文件路径不正确，缺少文件后缀名。");
    //            throw new Exception("输入的文件路径不正确，缺少文件后缀名。");
    //        }
    //        try
    //        {
    //            _codeText = File.ReadAllText(filePath);
    //        }
    //        catch (Exception ex)
    //        {
    //            throw new Exception("读取文件不成功：" + ex);
    //        }
    //    }

    //    /// <summary>
    //    /// 判断当前类对象是否合法
    //    /// </summary>
    //    /// <returns></returns>
    //    public bool IsValid()
    //    {
    //        if (Name == null || Name == "") return false;
    //        if (Type == null || Type == "") return false;
    //        if (CodeText == null || CodeText == "") return false;
    //        return true;
    //    }

    //    public IOperator CreateOprInstance(Dictionary<string, object> oprInfo)
    //    {
    //        IOperator opr;
    //        if (Type == "cs")// 如果是cs文件生成的模型
    //        {
    //            try
    //            {
    //                opr = CSScript.Evaluator.LoadCode<IOperator>(CodeText, new object[] { oprInfo });
    //            }
    //            catch (Exception ex)
    //            {
    //                Trace.TraceError($"根据代码文件{Name}Opr.{Type}生成算子对象有错误。");
    //                throw new Exception($"根据代码文件{Name}Opr.{Type}生成算子对象有错误：" + ex);
    //            }
    //        }
    //        else
    //        {
    //            Trace.TraceError($"不支持根据{Type}类型文件生成算子对象。");
    //            throw new Exception($"不支持根据{Type}类型文件生成算子对象。");
    //        }
    //        return opr;
    //    }
    //}
}
